package com.yao2san.sim.storage.client.core.integrate;

import com.aliyun.oss.OSS;
import com.qcloud.cos.COSClient;
import com.yao2san.sim.storage.client.config.*;
import com.yao2san.sim.storage.client.core.enums.StorageType;
import com.yao2san.sim.storage.client.core.event.UploadResult;
import com.yao2san.sim.storage.client.core.policy.FileRenamePolicy;
import com.yao2san.sim.storage.client.core.policy.FolderPolicy;
import com.yao2san.sim.storage.client.core.uploader.*;
import com.yao2san.sim.storage.client.exception.UploadErrorException;
import com.yao2san.sim.storage.client.exception.StorageInstanceNotFoundException;
import com.yao2san.sim.storage.client.util.StorageUtil;
import io.minio.MinioClient;
import org.springframework.context.ApplicationContext;

import java.io.IOException;
import java.io.InputStream;
import java.util.ServiceLoader;

import static com.yao2san.sim.storage.client.core.enums.StorageType.*;
import static com.yao2san.sim.storage.client.core.integrate.IntegrateAdapterUtil.getClient;
import static com.yao2san.sim.storage.client.core.integrate.IntegrateAdapterUtil.getProperties;

/**
 * @author wxg
 **/
public class IntegrateUploader extends AbstractIntegrateUploader {
    private final SimStorageClientProperties clientProperties;
    private final IntegrateConfig integrateConfig;
    private final ApplicationContext applicationContext;
    private final FolderPolicy folderPolicy;

    private final FileRenamePolicy fileRenamePolicy;

    private final Uploader uploader;
    public IntegrateUploader(SimStorageClientProperties clientProperties, IntegrateConfig integrateConfig, ApplicationContext applicationContext, FolderPolicy folderPolicy, FileRenamePolicy fileRenamePolicy) {
        this.clientProperties = clientProperties;
        this.integrateConfig = integrateConfig;
        this.applicationContext = applicationContext;
        this.folderPolicy = folderPolicy;
        this.fileRenamePolicy = fileRenamePolicy;
        this.uploader = getUploader();
    }

    @Override
    public UploadResult upload(InputStream stream, String dest, UploadArgs args) throws IOException, UploadErrorException {
        StorageUtil.checkObjectName(dest);
        //Uploader uploader = getUploader();
        return uploader.upload(stream, dest, args);
    }

    private Uploader getUploader() {
        Uploader uploader = null;
        StorageType storageType = integrateConfig.getStorageType();
        if (storageType.equals(LOCAL)) {
            uploader = new LocalUploader((LocalProperties) getProperties(integrateConfig), applicationContext, folderPolicy, fileRenamePolicy);
        }
        if (storageType.equals(FTP)) {
            uploader = new FtpUploader();
        }
        if (storageType.equals(MINIO)) {
            uploader = new MinioUploader((MinioClient) getClient(integrateConfig), (MinioProperties) getProperties(integrateConfig), applicationContext, folderPolicy);
        }
        if (storageType.equals(ALI_OSS)) {
            uploader = new AliOssUploader((OSS) getClient(integrateConfig), (AliOssProperties) getProperties(integrateConfig), applicationContext, folderPolicy);
        }
        if (storageType.equals(TENCENT_COS)) {
            uploader = new TencentCosUploader((COSClient) getClient(integrateConfig), (TencentCosProperties) getProperties(integrateConfig), applicationContext, folderPolicy);
        }
        if (storageType.equals(QI_NIU)) {
            //TODO
        }

        //custom storage type with spi
        if (storageType.equals(CUSTOM)) {
            String customType = clientProperties.getCustomType();
            if (customType == null || customType.isEmpty()) {
                throw new IllegalArgumentException("Custom type can not be empty, please check your config");
            }
            ServiceLoader<Uploader> serviceLoader = ServiceLoader.load(Uploader.class);
            for (Uploader service : serviceLoader) {
                if (customType.equalsIgnoreCase(service.getName())) {
                    uploader = service;
                    break;
                }
            }
            if (uploader == null) {
                throw new StorageInstanceNotFoundException("Custom uploader not found:" + customType + ", please check your config");
            }
        }

        if (uploader == null) {
            throw new StorageInstanceNotFoundException(integrateConfig.getStorageType().name());
        }
        return uploader;
    }


    @Override
    public String getName() {
        return INTEGRATE.name();
    }
}
